package view.editorview;

import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import controller.editorcontroller.EditorAreaListener;
import view.commonview.CircuitTypeArea;
import view.commonview.ConnectorPath;
import view.commonview.InfoPanel;
import view.commonview.LogicViewElement;
import view.commonview.TabbedPane;
import view.commonview.ToolBar;
import locsi.UserSettings;
import model.LogicType;
import model.editormodel.EditorModel;
import model.editormodel.Input;
import model.editormodel.Output;

/**
 * <b>Erbt:</b> <code>JPanel</code> <br>
 * <b>In Verbindung stehende Klassen:</b> <code>EditorArea, ComponentPanel,
 * EditorToolPanel</code><br>
 * <b>Funktion:</b> Repraesentation Bearbeitungsmodus <br>
 * <br>
 * Panel, auf dem <code>EditorArea</code>, <code>ComponentPanel</code> und
 * <code>EditorToolPanel</code> liegen.
 * 
 * @author Team Locsi
 * 
 */
@SuppressWarnings("serial")
public class EditorPanel extends JPanel {

	/*
	 * Referenzen auf andere View-Objekte
	 */
	private EditorArea editorArea;
	private EditorToolPanel eToolPanel;
	private ComponentPanel compPanel;
	private JScrollPane compScroller;
	private JScrollPane editorScroller;
	
	/**
	 * Dieser Konstruktor erzeugt ein neues <code>EditorPanel</code> - Objekt,
	 * wobei auch die Objekte <code>EditorArea</code>,
	 * <code>ComponentPanel</code> und <code>EditorToolPanel</code> erzeugt
	 * werden.
	 * 
	 * @param eModel
	 *            <code>EditorModel</code> - Referenz auf das
	 *            <code>EditorModel</code>
	 * @param tabs
	 *            <code>TabbedPane</code> - Referenz auf das
	 *            <code>TabbedPane</code>
	 * @param cta
	 *            <code>CircuitTypeArea</code> - Referenz auf die
	 *            <code>CircuitTypeArea</code>
	 * 
	 * @param tools
	 *            <code>ToolBar</code> - Referenz auf die <code>ToolBar</code>
	 */
	public EditorPanel(final EditorModel eModel, TabbedPane tabs,
			CircuitTypeArea cta, ToolBar tools, InfoPanel infoPanel) {

		// erzeugen der drei Bereiche Bauteilauswahlliste, Bearbeitungsbereich,
		// Werkzeugleiste
		this.compPanel = new ComponentPanel(eModel, tools);
		this.editorArea = new EditorArea(eModel, cta, compPanel, tabs,
				infoPanel.getInfoArea());
		this.eToolPanel = new EditorToolPanel(tabs, eModel, editorArea,
				infoPanel);

		final EditorAreaListener eAreaListener = new EditorAreaListener(editorArea,
				tools, eModel, tabs, compPanel);
		this.editorArea.addMouseListener(eAreaListener);
		this.editorArea.addMouseMotionListener(eAreaListener);

		// hinzufuegen einer input und actionmap um auf das druecken der
		// entfernen taste zu reagieren
		this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
				KeyStroke.getKeyStroke("DELETE"), "delete");
		this.getActionMap().put("delete", new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				List<String> markedElementsNames = editorArea
						.getNamesOfSelectedElements();
				List<ConnectorPath> markedPaths = editorArea
						.getMarkedConnectorPaths();
				
				//falls keine linien und elements markiert sind kann
				//sofort abgebrochen werden
				if (markedPaths.isEmpty() && markedElementsNames.isEmpty()) {
					return;
				}
				
				Map<Input, Output> deleteConnections = new HashMap<Input, Output>();

				// loeschen der markierten linien
				for (int i = 0; i < markedPaths.size(); i++) {
					deleteConnections.put(markedPaths.get(i).getTarget(),
							markedPaths.get(i).getSource());
				}

				// loeschen aller markierten Linien im EditorModel
				eModel.deleteConnections(deleteConnections);

				// loeschen aller markierten Elemente im EditorModel
				eModel.deleteLogicElements(markedElementsNames);
			}
		});
		
		//easter-egg-funktionen
		this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
				KeyStroke.getKeyStroke("shift DELETE"), "easterEgg");
		this.getActionMap().put("easterEgg", new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				eAreaListener.generateRandomCircuit(16);
			}
		});
		this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
				KeyStroke.getKeyStroke("shift U"), "uglyLamp");
		this.getActionMap().put("uglyLamp", new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				UserSettings.uglyLamp = !UserSettings.uglyLamp;
				for (LogicViewElement lVE : editorArea.getLogicViewElements()) {
					if (eModel.getCircuitModel().getUnmodifableElementsOnEditor().get(lVE.getElementsName()).getType() == LogicType.LAMP) {
						lVE.resetDesign(LogicType.LAMP, lVE.getSourceX(), lVE.getSourceY(), -1);
					}
				}
				editorArea.revalidate();
				editorArea.repaint();
			}
		});
		this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
				KeyStroke.getKeyStroke("alt shift A"), "alarm");
		this.getActionMap().put("alarm", new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try {
					Desktop.getDesktop().browse(new URI("http://www.youtube.com/watch?v=IkBqONnbCrg"));
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		
		
		// erzeugen der Scrollpanes
		this.compScroller = new JScrollPane(compPanel);
		this.compScroller
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		this.compScroller
				.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		compScroller.setMaximumSize(new Dimension(compScroller
				.getPreferredSize().width,
				compScroller.getPreferredSize().height));
		compScroller.setPreferredSize(new Dimension(compScroller
				.getPreferredSize().width,
				compScroller.getPreferredSize().height));
		compScroller.setSize(new Dimension(
				compScroller.getPreferredSize().width, compScroller
						.getPreferredSize().height));
		this.editorScroller = new JScrollPane(editorArea);
		this.editorArea.setScrollPane(editorScroller);
		this.editorScroller
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		this.editorScroller
				.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

		// erzeugen des Layouts
		this.setLayout(new BorderLayout());
		this.add(compScroller, BorderLayout.WEST);
		this.add(editorScroller, BorderLayout.CENTER);
		this.add(eToolPanel, BorderLayout.SOUTH);
	}

	/**
	 * Diese Methode gibt die <code>EditorArea</code> zurueck.
	 * 
	 * @return <code>EditorArea</code> - die <code>EditorArea</code>
	 */
	public EditorArea getEditorArea() {
		return editorArea;
	}

	/**
	 * Diese Methode gibt das <code>EditorToolPanel</code> zurueck.
	 * 
	 * @return <code>EditorToolPanel</code> - das <code>EditorToolPanel</code>
	 */
	public EditorToolPanel getEditorToolPanel() {
		return eToolPanel;
	}	
}